import {Injectable} from '@nestjs/common';
import {SaveBlogDto} from './dto/save-blog.dto';
import {UpdateBlogDto} from './dto/update-blog.dto';
import {BlogEntity} from "./entities/blog.entity";
import {InjectEntityManager, InjectRepository} from "@nestjs/typeorm";
import {EntityManager, Equal, In, Like, Repository} from "typeorm";
import {BlogTagEntity} from "./entities/blog-tag.entity";
import {BlogTagsEntity} from "./entities/blogTags.entity";
import {instanceToPlain, plainToInstance} from "class-transformer";
import {ResultData} from "../../common/utils/result";
import {AppHttpCode} from "../../common/enums/code.enum";
import {UpdateBlogTagsDto} from "./dto/save-blog-tags.dto";
import {QueryBlogDto} from "./dto/query-blog.dto";
import {uniqueObjectArrayFunc} from "../../common/utils/utils";
import {ReturnBlogDto} from "./dto/return-blog.dto";
import {QueryTagsDto} from "./dto/query-tags.dto";
import {DiscussEntity} from "../discuss/entities/discuss.entity";

@Injectable()
export class BlogsService {
  constructor(
    @InjectRepository(BlogEntity)
    private readonly blogEntityRepo: Repository<BlogEntity>,
    @InjectRepository(BlogTagsEntity)
    private readonly blogTagsEntityRepo: Repository<BlogTagsEntity>,
    // 中间表
    @InjectRepository(BlogTagEntity)
    private readonly blogTagEntityRepo: Repository<BlogTagEntity>,
    @InjectEntityManager()
    private readonly blogEntityManager: EntityManager,
    @InjectRepository(DiscussEntity)
    private readonly DiscussEntityRepo: Repository<DiscussEntity>,
  ) {
  }
  async createBlog(createBlogDto: SaveBlogDto) {
    console.log(createBlogDto)

    // 获取标签列表，开启事务
    //    新增一条数据
    const blog = await this.blogEntityManager.transaction(async (transactionalEntityManager) => {
      const blogResult = await transactionalEntityManager.save<BlogEntity>(plainToInstance(BlogEntity, createBlogDto));
      return this.addBlogTagByNos({id:Number(blogResult.id)},createBlogDto.tagList || [])
    })
    if (!blog) return ResultData.fail(AppHttpCode.SERVICE_ERROR, '博客创建失败');
    //    往标签表中插入多条标签
    return ResultData.ok('', '操作成功')
  }

  async updateBlog(updateBlogDto: UpdateBlogDto){
    const saveRes = await this.blogEntityManager.transaction(async (transactionalEntityManager) => {
      // 判断博客标签是否已经存在
      const tempDto = {...updateBlogDto};
      delete tempDto.id;
      // 获取标签信息
      const tags = tempDto.tagList;
      delete tempDto.tagList;
      // 更新中间表tag信息
      const deleteRes = await this.blogTagEntityRepo.delete({
        blogId: updateBlogDto.id
      })
      if(!deleteRes ) return null;
      const addTagRes = await this.addBlogTagByNos({id:updateBlogDto.id},tags)
      if(!addTagRes) return null;
      return await transactionalEntityManager.update<BlogEntity>(BlogEntity, updateBlogDto.id, {...tempDto})
    })
    if(!saveRes) {
      return ResultData.fail(500,'文章更新失败，请检查参数！',null)
    }
    return ResultData.ok(null,'文章更新成功!')
  }
  async deleteBlogItem(id:number){
    const findItem = await this.blogEntityRepo.findOne({where:{
        id
      }})
    if(!findItem){
      return ResultData.fail(500,'文章不存在！',null)
    }
    const deleteRes = await this.blogEntityRepo.delete({id})
    if(!deleteRes) {
      return ResultData.fail(500,'文章删除失败！',null)
    }
    return ResultData.ok(null,'文章删除成功！')
  }
  async getBlogContent(id: number){
    const res = await this.blogEntityRepo.findOne({
      where:{
        id
      }
    })
    if(!res) {
      return ResultData.fail(500,'博客内容获取失败',null)
    }
    return ResultData.ok(res,'博客内容获取成功')
  }
  async getBlogs(queryBlogDto:QueryBlogDto){
    const queryCondition = {...queryBlogDto};
    const { size = 10, page=1,key,blogType } = queryCondition
    const res =await  this.blogEntityRepo.createQueryBuilder('blogs')
      .leftJoinAndMapMany('blogs.tagsList',BlogTagEntity,'blogTag','blogs.id=blogTag.blog_id')
      .leftJoinAndMapMany('blogs.discussList',DiscussEntity,'blogDiscuss','blogs.id=blogDiscuss.blog_id')
      .where(
          {
            blogContent: Like(`%${key || ''}%`),
            blogType: Equal(Number(blogType)),
            enable: Equal(true)
          },
      )
      .orderBy({
        "blogs.createDate": "DESC",
        "blogs.updateDate": "DESC",
      })
      .skip(size * (page - 1))
      .take(size)
      .getManyAndCount()
    const tempRes = instanceToPlain(res[0]) as ReturnBlogDto[];
    const tempTagList = tempRes.map(v=>v.tagsList || []).flat()
    // 根据获取到的key，找到对应的标签列表
    const tagsList =uniqueObjectArrayFunc(tempTagList,'tagId')
    // console.log(tagsList)
    //  获取id数组
    const idsList = tagsList.map(v=>v.tagId);
    const tagsRes = await this.blogTagsEntityRepo.find({
      where: {
        id: In(idsList)
      }
    })
    // 替换res
    const replacedTagsList = tempTagList.map(v=> {
      const findItem = (tagsRes || []).find(i=>i.id===v.tagId);
      if(findItem){
        return {...findItem,relationId: v.id,blogId:v.blogId}
      }
      return undefined
    })
    const reData = (tempRes || []).map(v=> {
      const filterTags = replacedTagsList.filter(i=>i.blogId===v.id)
      const copyVal = {...v};
      const discussCount = v.discussList.length;
      delete v.discussList;
      delete v.blogContent;
      return {
        ...v,
        tagsList: filterTags || [],
        discussCount,
      }
    })
    // 找到所有id的
    const count = res[1]
    return ResultData.ok({
      list:reData,
      total: count
    },'查询成功')
  //   拼接每一个的标签列表
  }
  async addBlogTagByNos(blogEntity: {
    id:number
  },tags:number[] ){
    const link = await this.blogEntityManager.transaction(async (transactionalEntityManager) => {
      await this.blogTagEntityRepo.delete({
        blogId: Number(blogEntity.id)
      });
      const createTgsDto = (tags || []).map(v=> ({
        blogId: blogEntity.id,
        tagId: v,
      }))
      const tagsResult = await transactionalEntityManager.save<BlogTagEntity>(plainToInstance(BlogTagEntity, createTgsDto));
      return tagsResult
    })
    if (!link) return false;
    //    往标签表中插入多条标签
    return true
  }
  async getBlogTags(queryTagsDto:QueryTagsDto){
    const otherCondition = queryTagsDto.enable===undefined ? undefined: {
      enable: queryTagsDto.enable
    }
   const tags = await this.blogTagsEntityRepo.find({
      where:[
        {
          tagName: Like('%'+(queryTagsDto.key || '')+'%')
        },
        {
          tagDesc: Like('%'+(queryTagsDto.key || '')+'%')
        },
        otherCondition
      //     是否可用
      ].filter(v=>!!v)
   });
   return ResultData.ok(tags,'获取博客标签成功')
  }

  async createBlogTag(updateBlogTagsDto: UpdateBlogTagsDto){
    const tempDto = {...updateBlogTagsDto,id:null}
    // 判断博客标签是否已经存在
    const findItem = await this.blogTagsEntityRepo.findOne({where:{
      tagName: updateBlogTagsDto.tagName
      }})
    if(findItem) {
      return ResultData.fail(500,'博客标签已经存在！',null)
    }
    const saveRes = await this.blogTagsEntityRepo.save(tempDto,{
      transaction:true
    })
    if(!saveRes) {
      return ResultData.fail(500,'博客标签新增失败，请检查参数！',null)
    }
    return ResultData.ok(saveRes,'博客标签新增成功')
  }
  async updateBlogTag(updateBlogTagsDto: UpdateBlogTagsDto){
    // 判断博客标签是否已经存在
    const findItem = await this.blogTagsEntityRepo.findOne({where:{
        tagName: updateBlogTagsDto.tagName
      }})
    if(!findItem) {
      return ResultData.fail(500,'博客标签不存在！',null)
    }
    const saveRes = await this.blogTagsEntityRepo.update(updateBlogTagsDto.id,updateBlogTagsDto)
    if(!saveRes) {
      return ResultData.fail(500,'博客标签更新失败，请检查参数！',null)
    }
    return ResultData.ok(null,'博客标签更新成功!')
  }

  async deleteBlogTag(id:number){
    const findItem = await this.blogTagsEntityRepo.findOne({where:{
        id
      }})
    if(!findItem){
      return ResultData.fail(500,'博客标签不存在！',null)
    }
    const deleteRes = await this.blogTagsEntityRepo.delete({id})
    if(!deleteRes) {
      return ResultData.fail(500,'博客标签删除失败！',null)
    }
    return ResultData.ok(null,'博客标签删除成功！')
  }
}
